package Server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.time.LocalDate;
import java.util.ArrayList;

import Commons.Karte;
import Commons.Spieler;
import Commons.Spielzustand;

/**
 * @author Alex
 *
 */
public class ClientThread extends Thread {
	
	Socket socket;
	ObjectInputStream objectInputStream;
	ObjectOutputStream objectOutputStream;
	VerbindungsAufbauServer verbindungsAufbauServer;
	String Threadname;
	String Username;
	ArrayList<Karte> vierzehnSpieler1 = new ArrayList<>();
	ArrayList<Karte> vierzehnSpieler2 = new ArrayList<>();

	public ClientThread(VerbindungsAufbauServer verbindungsAufbauServer, Socket socket, String Threadname, String Username) throws IOException {
		this.socket = socket;
		this.objectInputStream = new ObjectInputStream(socket.getInputStream());
		this.objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
		this.verbindungsAufbauServer = verbindungsAufbauServer;
		this.Threadname = Threadname;
		this.Username = Username;
	}
	
	public void run(){
		listen();
	}

	public void close() {
		try {
			this.interrupt(); // stop waiting for messages			
			socket.close();
		} catch (IOException e) {
			// We are closing - do nothing
		}
	}
	
	private void listen() {
		Spieler spieler = null;
		Object object = null;
		Spiellogik spiellogik = null;
		Spielzustand spielzustand = null;
		try{
			while ((object = objectInputStream.readObject()) != null) {
				//Spiellogik vom Server holen
				spiellogik = verbindungsAufbauServer.getSpiellogik();
				
				if (object instanceof Spielzustand) {
					//Spielzustand wird zum Server synchronisiert
					spielzustand = (Spielzustand)object; 
					spiellogik.setSpielzustand(spielzustand);
					System.out.println("Spielzustand-received:" + spielzustand);
				}
				else if (object instanceof Spieler){
					spieler = (Spieler)object;
					System.out.println("spieler-received: "+spieler);
				}
							
				if (verbindungsAufbauServer.clientlist.size() <= 1) {
					//Erster Spieler wird registiert
					System.out.println("Do nothing as we only have one client till now");
					if (spieler != null) {
						spiellogik.getSpielzustand().setSpieler(spieler);
					}
				} else {
					//Zweiter Spieler wird registiert
					if ((spieler != null) && 
						(spiellogik.getSpielzustand().isGemischteKartenGesendet() == false)) {
						spiellogik.getSpielzustand().setSpieler(spieler);
						sendeGemischteKarten(spiellogik.getSpielzustand());
						spiellogik.getSpielzustand().setGemischteKartenGesendet(true);
					}
					else {
					// Gespielte Karten werden behandelt
					System.out.println(spiellogik.getSpielzustand().getSpieler(0).isGegnerHatGespielt());
					System.out.println(spiellogik.getSpielzustand().getSpieler(1).isGegnerHatGespielt());
						
					if ((spiellogik.getSpielzustand() != null) && 
						   ((spiellogik.getSpielzustand().getSpieler(0).isGegnerHatGespielt() == false) && 
						   (spiellogik.getSpielzustand().getSpieler(1).isGegnerHatGespielt() == true))) {
							System.out.println("----------------getSpielzustand Teil 1----------------");
							
							boolean rundenGewinnerErmitteln = false;
							rundenGewinnerErmitteln = spiellogik.rundenGewinnerErmitteln(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1), spiellogik.getSpielzustand());
							System.out.println("-----------------------------Rundengewinner ermitteln Teil 1" + rundenGewinnerErmitteln);
							
							spiellogik.getSpielzustand().setRangLatte(0);
							spiellogik.spielen(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
							
							verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
							System.out.println("Spieler 1 hat gespielt-- Spieler 2 nicht");
							
						} 
						else if ((spiellogik.getSpielzustand() != null) && 
								((spiellogik.getSpielzustand().getSpieler(0).isGegnerHatGespielt() == true) && 
								(spiellogik.getSpielzustand().getSpieler(1).isGegnerHatGespielt() == false))) {
							System.out.println("----------------getSpielzustand Teil 2----------------");
							
							boolean rundenGewinnerErmitteln = false;
							rundenGewinnerErmitteln = spiellogik.rundenGewinnerErmitteln(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1), spiellogik.getSpielzustand());
							System.out.println("-----------------------------Rundengewinner ermitteln Teil 2" + rundenGewinnerErmitteln);
							
							
							
							spiellogik.getSpielzustand().setRangLatte(0);
							spiellogik.spielen(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
							
							verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
							System.out.println("Spieler 2 hat gespielt-- Spieler 1 nicht");
							
							
							
							
							//2 Spieler haben gespielt-- hier muss Spiellogik kontrolliert werden
							
						} else if ((spiellogik.getSpielzustand() != null) && 
								  ((spiellogik.getSpielzustand().getSpieler(0).isGegnerHatGespielt() == true) && 
								  (spielzustand.getSpieler(1).isGegnerHatGespielt() == true))) {
							System.out.println("Spieler 1 und Spieler 2 haben einmal gespielt--- hier muss stichgewinner ermittelt werden");
							
							
							//spiellogik.stichGewinnerErmitteln(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1), spiellogik.getSpielzustand());
							
							
		
							
							System.out.println("Rundengweinner ist" + spiellogik.getSpielzustand().getSpieler(0).isRundenBeginner());
							System.out.println("Rundengweinner ist" + spiellogik.getSpielzustand().getSpieler(1).isRundenBeginner());
							

							System.out.println(spiellogik.getSpielzustand().getSpieler(0).getStichPunkte());
							System.out.println(spiellogik.getSpielzustand().getSpieler(1).getStichPunkte());
							
							
							
							System.out.println("-----------------------------Rundengewinner ermitteln Teil 2");
							
							
							
							//spiellogik.spielErlaubnisServer(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
							System.out.println("--------davor Spieler 1 hat gepasst-----------------------" +spiellogik.getSpielzustand().getSpieler(0).isHatGepasst());
							if(spiellogik.getSpielzustand().getSpieler(0).isHatGepasst() == true)
							{
								System.out.println("--------Spieler 1 hat gepasst-----------------------");
								
								spiellogik.passen(spiellogik.getSpielzustand(), spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
								System.out.println("Stichgewinner-- Spieler 1: "+ spiellogik.getSpielzustand().getSpieler(0).isStichGewinner() );
								System.out.println("Stichgewinner-- Spieler 2: "+ spiellogik.getSpielzustand().getSpieler(1).isStichGewinner() );
								verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
								
							}else if(spiellogik.getSpielzustand().getSpieler(1).isHatGepasst() == true)
							{
								
								
								System.out.println("--------Spieler 2 hat gepasst-----------------------");
								spiellogik.passen(spiellogik.getSpielzustand(), spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
								System.out.println("Stichgewinner-- Spieler 1: "+ spiellogik.getSpielzustand().getSpieler(0).isStichGewinner() );
								System.out.println("Stichgewinner-- Spieler 2: "+ spiellogik.getSpielzustand().getSpieler(1).isStichGewinner() );
								verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
							}
							if (spiellogik.spielErlaubnisServer(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1)) == true) {
								
								
								System.out.println("***********hat er gepasst     " + spiellogik.getSpielzustand().getSpieler(0).isHatGepasst());
								
								if(spiellogik.getSpielzustand().getSpieler(0).isHatGepasst() == false){
								
								System.out.println("----------Spieler darf spielen--> broadcasten---------------");
								boolean rundenGewinnerErmitteln = false;
								rundenGewinnerErmitteln = spiellogik.rundenGewinnerErmitteln(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1), spiellogik.getSpielzustand());
								if(rundenGewinnerErmitteln == false){
								spiellogik.spielen(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
								
								
								System.out.println("Ranglatte ----------------------- " +spielzustand.getRangLatte() + "--------------------------------");
								
								verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
								}else{
									verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
								}
								
								
								} else
									
									if(spiellogik.getSpielzustand().getSpieler(1).isHatGepasst() == true){
										
										System.out.println("----------Spieler darf spielen--> broadcasten---------------");
										boolean rundenGewinnerErmitteln = false;
										rundenGewinnerErmitteln = spiellogik.rundenGewinnerErmitteln(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1), spiellogik.getSpielzustand());
										if(rundenGewinnerErmitteln == false){
										spiellogik.spielen(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1));
										
										
										System.out.println("Ranglatte ----------------------- " +spielzustand.getRangLatte() + "--------------------------------");
										
										verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
										}else{
											verbindungsAufbauServer.broadcast(spiellogik.getSpielzustand());
										}
										
										
										}
									
									
									
							}
								
							else if (spiellogik.spielErlaubnisServer(spiellogik.getSpielzustand().getSpieler(0), spiellogik.getSpielzustand().getSpieler(1)) == false) {
								System.out.println("Spieler darf nicht spielen--> broadcasten");
								senderrormessagetoclient(spiellogik.getSpielzustand());
							}
							
							

					}				
				}
				} // end else
				
				//Spiellogik auf Server synchronisieren
				if (spiellogik != null) {
					verbindungsAufbauServer.setSpiellogik(spiellogik);
				}
			} // end while
	}
		catch (Exception e){
			e.printStackTrace();
	}
	}
	
	private void sendeGemischteKarten(Spielzustand spielzustand) throws IOException, ClassNotFoundException, InterruptedException {


		HaggisRandom haggisRandom = new HaggisRandom();
		spielzustand.setHaggis(haggisRandom.getHaggisKarten());
		System.out.println("sendeGemischteKarten has been sent to the broadcast method to send to the clients");
		
		haggisRandom.generateHaggisKarten();
		
		//TODO Juergen error handling
		spielzustand.getSpieler(0).setVierzehnSpieler1(haggisRandom.getVierzehnSpieler1());
		spielzustand.getSpieler(1).setVierzehnSpieler2(haggisRandom.getVierzehnSpieler2());
		spielzustand.setHaggis(haggisRandom.getHaggisKarten());
		
		try {
			DBZugriff.einfuegen(spielzustand.getSpieler(0).getSpielername(), spielzustand.getSpieler(0).getGesammeltenPunkte(), LocalDate.now());
			DBZugriff.einfuegen(spielzustand.getSpieler(1).getSpielername(), spielzustand.getSpieler(1).getGesammeltenPunkte(), LocalDate.now());

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	
		
		
		verbindungsAufbauServer.getSpiellogik().ersterSpielerErmitteln(spielzustand.getSpieler(0), spielzustand.getSpieler(1));

		
		
	

		verbindungsAufbauServer.broadcast(spielzustand);
		
	}
	
	public void senderrormessagetoclient (Spielzustand spielzustand) throws IOException, InterruptedException {
		spielzustand.setHatFalscheKombinationGespielt(true);
		this.objectOutputStream.writeObject(spielzustand);
		System.out.println("HHHHHHHHHHAAAAAAAAAAAAAAAAAHHHHHHHHHHAAAAAAAAAAAAAAA");
		
	}
	

	public String getThreadname() {
		return Threadname;
	}

	public void setThreadname(String threadname) {
		this.Threadname = threadname;
	}
	
	

	public String getUsername() {
		return Username;
	}
	
	

}
